# Power Loss Recovery

# uncomment if you not using it yet:

#[force_move]

#[save_variables]
#filename: ~/printer_data/config/variables.cfg


[gcode_macro POWER_LOSS_RECOVERY]
gcode:
  {% if printer.save_variables.variables.power_loss_recovery|default(0)|int == 1 %}
    M118 Restoring print after power loss
    M117 File: {printer.save_variables.variables.pl_file_path}

    # load file
    M23 {printer.save_variables.variables.pl_file_path}
    M26 S{printer.save_variables.variables.pl_file_position}

    # heating up
    M104 S{printer.save_variables.variables.pl_extruder_temp|int}
    M140 S{printer.save_variables.variables.pl_bed_temp|int}

    M109 S{printer.save_variables.variables.pl_extruder_temp|int}
    M190 S{printer.save_variables.variables.pl_bed_temp|int}

    G28 X Y
    SET_GCODE_OFFSET Z={printer.save_variables.variables.pl_z_offset} MOVE=0
    # big enough value to cover safe_z_home.z_hop value
    SET_KINEMATIC_POSITION Z=20

    # default speed for prepare movements
    G1 F{50 * 60}

    # move to position and left a little before poo
    G1 X{printer.save_variables.variables.pl_gcode_position_x - 5} Y{printer.save_variables.variables.pl_gcode_position_y}

    # lowering in case z home is active
    G91
    {% if "safe_z_home" in printer.configfile.config %}
      G1 Z-{printer.configfile.config.safe_z_home.z_hop}
    {% endif %}

    M117 Extruding filament before print, please remove ooze if possible
    # some extra poo
    M83
    G1 E2 F120

    M117 Moving to position
    # move to position
    {% if printer.save_variables.variables.pl_extra_z > 0 %}
      G1 Z-{printer.save_variables.variables.pl_extra_z}
    {% endif %}
    G1 X5

    # restoring all parameters
    M221 S{printer.save_variables.variables.pl_extrude_factor * 100}
    M220 S{printer.save_variables.variables.pl_speed_factor * 100}
    {% if printer.save_variables.variables.pl_absolute_extrude|default(False) %}
      M117 Absolute extrusion
      M82
    {% else %}
      M117 Relative extrusion
      M83
    {% endif %}
    {% if printer.save_variables.variables.pl_absolute_coordinates|default(False) %}
      M117 Absolute coordinates
      G90
    {% else %}
      M117 Relative coordinates
      G91
    {% endif %}
    SET_KINEMATIC_POSITION Z={printer.save_variables.variables.pl_kin_position_z}

    M117 Applying miscelanious parameters 

    SET_PRESSURE_ADVANCE ADVANCE={printer.save_variables.variables.pl_pressure_advance} SMOOTH_TIME={printer.save_variables.variables.pl_smooth_time}
    SET_VELOCITY_LIMIT ACCEL={printer.save_variables.variables.pl_accel} ACCEL_TO_DECEL={printer.save_variables.variables.pl_accel_to_decel} VELOCITY={printer.save_variables.variables.pl_velocity} SQUARE_CORNER_VELOCITY={printer.save_variables.variables.pl_sqv}

    # apply last speed
    G1 F{printer.save_variables.variables.pl_speed}
    M106 S{printer.save_variables.variables.pl_fan_speed|int}

    # resume printing
    M24
  {% endif %}


[gcode_macro POWER_LOSS]
gcode:
  M117 Power loss! Saving print state now!

  POWER_LOSS_SAVE

  # raising to not damage model
  G91
  G1 Z10

  SAVE_VARIABLE VARIABLE="pl_extra_z" VALUE=10

  # uncomment and change to desired park position
  #G90
  #G1 X0 Y0

  # save_config is optional, it's there for saving bed mesh, actually. can be safely commented out, and then pause may be uncommented
  SAVE_CONFIG
  #PAUSE


[gcode_macro POWER_LOSS_SAVE]
gcode:
  SAVE_VARIABLE VARIABLE="pl_file_path" VALUE="\"{printer.print_stats.filename}\""
  SAVE_VARIABLE VARIABLE="pl_file_position" VALUE={printer.virtual_sdcard.file_position}

  SAVE_VARIABLE VARIABLE="pl_speed_factor" VALUE={printer.gcode_move.speed_factor}
  SAVE_VARIABLE VARIABLE="pl_speed" VALUE={printer.gcode_move.speed}

  SAVE_VARIABLE VARIABLE="pl_extrude_factor" VALUE={printer.gcode_move.extrude_factor}
  SAVE_VARIABLE VARIABLE="pl_absolute_coordinates" VALUE={printer.gcode_move.absolute_coordinates}
  SAVE_VARIABLE VARIABLE="pl_absolute_extrude" VALUE={printer.gcode_move.absolute_extrude}

  SAVE_VARIABLE VARIABLE="pl_gcode_position_x" VALUE={printer.gcode_move.gcode_position.x}
  SAVE_VARIABLE VARIABLE="pl_gcode_position_y" VALUE={printer.gcode_move.gcode_position.y}
  SAVE_VARIABLE VARIABLE="pl_gcode_position_z" VALUE={printer.gcode_move.gcode_position.z}
  SAVE_VARIABLE VARIABLE="pl_gcode_position_e" VALUE={printer.gcode_move.gcode_position.e}

  SAVE_VARIABLE VARIABLE="pl_kin_position_x" VALUE={printer.toolhead.position.x}
  SAVE_VARIABLE VARIABLE="pl_kin_position_y" VALUE={printer.toolhead.position.y}
  SAVE_VARIABLE VARIABLE="pl_kin_position_z" VALUE={printer.toolhead.position.z}
  SAVE_VARIABLE VARIABLE="pl_kin_position_e" VALUE={printer.toolhead.position.e}

  SAVE_VARIABLE VARIABLE="pl_fan_speed" VALUE={printer.fan.speed * 255}

  SAVE_VARIABLE VARIABLE="pl_z_offset" VALUE={printer.gcode_move.homing_origin.z}

  SAVE_VARIABLE VARIABLE="pl_extruder_temp" VALUE={printer.extruder.target}
  SAVE_VARIABLE VARIABLE="pl_bed_temp" VALUE={printer.heater_bed.target}

  SAVE_VARIABLE VARIABLE="pl_pressure_advance" VALUE={printer.extruder.pressure_advance}
  SAVE_VARIABLE VARIABLE="pl_smooth_time" VALUE={printer.extruder.smooth_time}

  SAVE_VARIABLE VARIABLE="pl_retract_length" VALUE={printer.firmware_retraction.retract_length}
  SAVE_VARIABLE VARIABLE="pl_retract_speed" VALUE={printer.firmware_retraction.retract_speed}
  SAVE_VARIABLE VARIABLE="pl_unretract_speed" VALUE={printer.firmware_retraction.unretract_speed}

  SAVE_VARIABLE VARIABLE="pl_velocity" VALUE={printer.toolhead.max_velocity}
  SAVE_VARIABLE VARIABLE="pl_accel" VALUE={printer.toolhead.max_accel}
  SAVE_VARIABLE VARIABLE="pl_accel_to_decel" VALUE={printer.toolhead.max_accel_to_decel}
  SAVE_VARIABLE VARIABLE="pl_sqv" VALUE={printer.toolhead.square_corner_velocity}

  SAVE_VARIABLE VARIABLE="pl_extra_z" VALUE=0


[gcode_macro M413]
gcode:
  {% if not "S" in params %}
    {% if printer.save_variables.variables.power_loss_recovery|default(0)|int == 1 %}
      M118 Power-loss recovery ON
    {% else %}
      M118 Power-loss recovery OFF
    {% endif %}
  {% else %}
    SAVE_VARIABLE VARIABLE="power_loss_recovery" VALUE={params.S}
  {% endif %}


[gcode_macro POWER_LOSS_TIMER_START]
gcode:
  UPDATE_DELAYED_GCODE ID=POWER_LOSS_SAVE DURATION=1


[gcode_macro POWER_LOSS_TIMER_STOP]
gcode:
  UPDATE_DELAYED_GCODE ID=POWER_LOSS_SAVE DURATION=0


[delayed_gcode POWER_LOSS_SAVE]
initial_duration: 0
gcode:
  POWER_LOSS_SAVE
  UPDATE_DELAYED_GCODE ID=POWER_LOSS_SAVE DURATION=1